home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 June / Macworld (1999-06).dmg / Shareware World / Info / For Developers / MacZoop2.0.sea / MacZoop2.0 / Required Classes / ZComrade.cpp < prev    next >
Text File  |  1999-02-12  |  7KB  |  292 lines

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            MacZoop - "the framework for the rest of us"     
  5. *
  6. *
  7. *
  8. *            ZComrade.cpp    -- an object that can maintain loose links between objects
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include    "ZComrade.h"
  23. #include    "MacZoop.h"
  24.  
  25.  
  26. // this is a fudge to get around a limitation of the language- ZComrade requires ZObjectArray
  27. // for its lists, but ZObjectArray IS a ZComrade. Thus, since we are not allowed forward/
  28. // circular cross-dependencies like this, this struct is used to "pull" the declaration forward
  29. // so that everything compiles correctly.
  30.  
  31. class ZComradeList : public ZObjectList
  32. {
  33. };
  34.  
  35.  
  36.  
  37. CLASSCONSTRUCTOR( ZComrade );
  38.  
  39. /*---------------------------------***  CONSTRUCTOR  ***--------------------------------*/
  40.  
  41.  
  42. ZComrade::ZComrade()
  43. {
  44.     classID = CLASS_ZComrade;
  45.     talkers = listeners = NULL;
  46. }
  47.  
  48. /*---------------------------------***  DESTRUCTOR  ***---------------------------------*/
  49.  
  50. ZComrade::~ZComrade()
  51. {
  52.     // when we are destroyed, we need to make sure that we remove ourselves
  53.     // from any talker's list that we are part of, and make sure that any listeners
  54.     // that are listening to us no longer do so.
  55.     
  56.     long        n;
  57.     ZComrade*    aComrade;
  58.     
  59.     if( listeners )
  60.     {
  61.         n = listeners->CountItems();
  62.         
  63.         do
  64.         {
  65.             aComrade = (ZComrade*) listeners->GetObject( n );
  66.             
  67.             if( aComrade )
  68.                 aComrade->RemoveTalker( this );
  69.         }
  70.         while( --n );
  71.         
  72.         ForgetObject( listeners );
  73.     }
  74.     
  75.     if( talkers )
  76.     {
  77.         n = talkers->CountItems();
  78.         
  79.         do
  80.         {
  81.             aComrade = (ZComrade*) talkers->GetObject( n );
  82.             
  83.             if( aComrade )
  84.                 aComrade->RemoveListener( this );
  85.         }
  86.         while( --n );
  87.     
  88.         ForgetObject( talkers );
  89.     }
  90. }
  91.  
  92.  
  93. /*--------------------------------***  SENDMESSAGE  ***---------------------------------*/
  94. /*    
  95. transmit a message to anyone who is listening
  96. ----------------------------------------------------------------------------------------*/
  97.  
  98. void        ZComrade::SendMessage( long aMessage, void* msgData )
  99. {
  100.     // send the message to all of the listeners of this object
  101.  
  102.     long        n;
  103.     ZComrade*    aListener;
  104.     
  105.     if( listeners )
  106.     {
  107.         n = listeners->CountItems();
  108.         
  109.         do
  110.         {
  111.             aListener = (ZComrade*) listeners->GetObject( n );    
  112.             
  113.             if( aListener )
  114.                 aListener->ReceiveMessage( this, aMessage, msgData );
  115.         }
  116.         while( --n );    
  117.     }
  118. }
  119.  
  120. /*--------------------------------***  SENDMESSAGE  ***---------------------------------*/
  121. /*    
  122. transmit a message to anyone who is listening (via a message object)
  123. ----------------------------------------------------------------------------------------*/
  124.  
  125. void        ZComrade::SendMessage( ZMessage* aMessage )
  126. {
  127.     // send the message object to all of the listeners of this object
  128.     
  129.     long        n;
  130.     ZComrade*    aListener;
  131.     
  132.     if( listeners )
  133.     {
  134.         n = listeners->CountItems();
  135.         
  136.         do
  137.         {
  138.             aListener = (ZComrade*) listeners->GetObject( n );    
  139.             
  140.             if( aListener )
  141.                 aListener->ReceiveMessage( this, aMessage );
  142.         }
  143.         while( --n );    
  144.     }
  145. }
  146.  
  147.  
  148. /*---------------------------------***  LISTENTO  ***-----------------------------------*/
  149. /*    
  150. elect to listen to another comrade. We will receive any messages transmitted by that
  151. object whenever it sends them
  152. ----------------------------------------------------------------------------------------*/
  153.  
  154. void        ZComrade::ListenTo( ZComrade* aSender )
  155. {
  156.     // add this to the sender's list of listeners, and the sender to our list of talkers
  157.     
  158.     FailNILParam( aSender );
  159.     
  160.     // make sure we are not already listening to this one- references must be
  161.     // included exactly once
  162.     
  163.     if(( talkers == NULL ) || !talkers->Contains( aSender ))
  164.     {
  165.         aSender->AddListener( this );
  166.         AddTalker( aSender );
  167.     }
  168. }
  169.  
  170.  
  171. /*-----------------------------***  STOPLISTENINGTO  ***-------------------------------*/
  172. /*    
  173. we no longer want to receive messages from this transmitter
  174. ----------------------------------------------------------------------------------------*/
  175.  
  176. void        ZComrade::StopListeningTo( ZComrade* aSender )
  177. {
  178.     // remove this from the sender's list of listeners, and remove it from our list of talkers
  179.     
  180.     FailNILParam( aSender );
  181.     
  182.     // make sure we are really listening to it
  183.     
  184.     if (talkers && talkers->Contains( aSender ))
  185.     {
  186.         RemoveTalker( aSender );
  187.         aSender->RemoveListener( this );
  188.     }
  189. }
  190.  
  191.  
  192. /*---------------------------------***  ADDTALKER  ***----------------------------------*/
  193. /*    
  194. add a talker to our list of talkers
  195. ----------------------------------------------------------------------------------------*/
  196.  
  197. void        ZComrade::AddTalker( ZComrade* aTalker )
  198. {
  199.     // add the talker to the list of talkers
  200.     
  201.     if (talkers == NULL)
  202.         FailNIL( talkers = new ZComradeList());
  203.         
  204.     talkers->AppendItem( aTalker );
  205. }
  206.  
  207. /*-------------------------------***  ADDLISTENER  ***----------------------------------*/
  208. /*    
  209. add a listener to our list of listeners
  210. ----------------------------------------------------------------------------------------*/
  211.  
  212. void        ZComrade::AddListener( ZComrade* aListener )
  213. {
  214.     // add the listener to the list of listeners
  215.     
  216.     if (listeners == NULL)
  217.         FailNIL( listeners = new ZComradeList());
  218.         
  219.     listeners->AppendItem( aListener );
  220. }
  221.  
  222.  
  223. /*--------------------------------***  REMOVETALKER  ***--------------------------------*/
  224. /*    
  225. remove the talker from our list of talkers
  226. ----------------------------------------------------------------------------------------*/
  227.  
  228. void        ZComrade::RemoveTalker( ZComrade* aTalker )
  229. {
  230.     // remove this talker from the list of talkers
  231.     
  232.     if( talkers )
  233.     {
  234.         talkers->DeleteObject( aTalker );
  235.         
  236.         if( talkers->CountItems() <= 0 )
  237.             ForgetObject( talkers );
  238.     }
  239. }
  240.  
  241.  
  242. /*-------------------------------***  REMOVELISTENER  ***-------------------------------*/
  243. /*    
  244. remove the listener from our list of listeners
  245. ----------------------------------------------------------------------------------------*/
  246.  
  247. void        ZComrade::RemoveListener( ZComrade* aListener )
  248. {
  249.     // remove this listener from the list of listeners
  250.     
  251.     if( listeners )
  252.     {
  253.         listeners->DeleteObject( aListener );
  254.         
  255.         if( listeners->CountItems() <= 0 )
  256.             ForgetObject( listeners );
  257.     }
  258. }
  259.  
  260.  
  261. /*--------------------------------***  WRITETOSTREAM  ***-------------------------------*/
  262. /*    
  263. write talkers and listener refs to stream
  264. ----------------------------------------------------------------------------------------*/
  265.  
  266. void    ZComrade::WriteToStream( ZStream* aStream )
  267. {
  268. #if _MACZOOP_STREAMS
  269.     // note: ZStream permits NULL objects to be written to the stream, so we don't even
  270.     // need to check whether they're NULL or not.
  271.     
  272.     aStream->WriteObject( talkers );
  273.     aStream->WriteObject( listeners );
  274. #endif
  275. }
  276.  
  277.  
  278. /*-------------------------------***  READFROMSTREAM  ***-------------------------------*/
  279. /*    
  280. read from the stream- this re-establishes the entire comrade linkage from the stream.
  281. You should only call this when this comrade is first made, since any existing talkers
  282. or listeners objects will be left dangling.
  283. ----------------------------------------------------------------------------------------*/
  284.  
  285. void    ZComrade::ReadFromStream( ZStream* aStream )
  286. {
  287. #if _MACZOOP_STREAMS
  288.     talkers     = (ZComradeList*) aStream->ReadObject();
  289.     listeners     = (ZComradeList*) aStream->ReadObject();
  290. #endif
  291. }
  292.